#include <CoCoA/library.H>
#include <vector>

using namespace CoCoA;
using namespace std;

class MyRing {
	public:

		MyRing(const MyRing& ri) : __ring_ptr(ri.__ring_ptr), __created(false) {}

		const MyRing& operator=(const MyRing& ri) {
			__ring_ptr=ri.__ring_ptr;
			__created=false;
			return *this;
		}

		~MyRing() {
			cout << "dtor ..." << endl;	
			if(__created)
				delete __ring_ptr;	// would work, GlobalManager might be destroyed before this
		}
	
	private:
		MyRing(): __ring_ptr(NULL),__created(false) {}
		
		/*
		const MyRing& setPtr(SparsePolyRing* ptr){
			__ring_ptr=ptr;
			return *this;
		}
		*/
		const SparsePolyRing *__ring_ptr;
		bool __created;

	friend class vector<MyRing>; // tricky
	friend int main(); // tricky

	friend const MyRing& createRing();
	friend void deleteRing(MyRing& ri);
};

#define MAX_NUM_RINGS 6

vector<MyRing> MyRingPool(MAX_NUM_RINGS);

const MyRing& createRing() {
	static size_t count = 0;
	cout << "creating the " << count+1 << " ring" << endl;
	MyRingPool[count].__ring_ptr =  new SparsePolyRing(NewPolyRing(NewRingFp(17),symbols("x","y","z"))) ;
	MyRingPool[count].__created=true;
	return MyRingPool[count++];
}

/*
void deleteRing(MyRing& ri){
	// if ((ri.__created) && (ri.__ring_ptr != NULL)) {
	if (ri.__ring_ptr != NULL) {
		cout << "deleteing data" << endl;
		delete ri.__ring_ptr;
		ri.__ring_ptr=NULL; // only for flexibility
		// (const_cast<MyRing& >(ri)).__ring_ptr=NULL; // only for flexibility
		// const_cast<MyRing& >(ri).__created=false; //test const_cast
	}
}
*/

CoCoA::GlobalManager CoCoAinitialization;

int main(){
	MyRing R; // error: private ctor
	MyRing R1=createRing();
	MyRing R3(R1); //R3 does not need to be deleted
	MyRing R2=createRing(); 
	// const MyRing R2=createRing(); // can not be const, must be casted to delete
	/*
	deleteRing(R1);	
	deleteRing(R2);	
	deleteRing(R2);	//safe to do so
	*/
	// deleteRing(R3); //unsafe to do so, however, one might need to do const_cast	
	return 0;
}
